4 приема отладки запросов в типовых конфигурациях – на примере УТ 11.3 и УПП 1.3

В типовых конфигурациях используются массивные запросы до нескольких тысяч строк. Разобраться «с наскока» в таких запросах не получится.

Тексты этих запросов представляют собой пакеты с десятками временных таблиц.

Умение быстро просмотреть содержимое каждой временной таблицы (по сути – каждого отдельного этапа получения данных) существенно упрощает жизнь внедренцам, позволяет понять логику работы запроса, найти допущенную ошибку.

В текущей статье мы рассмотрим несколько приемов, которые помогут Вам анализировать и дорабатывать типовые конфигурации.

Начнем с ответа на популярный вопрос:

Как просмотреть содержимое временной таблицы?

Для примера рассмотрим конфигурацию «Управление торговлей», редакция 11.3.

Рисунок 1

При закрытии кассовой смены пробитые чеки ККМ архивируются, все данные о продажах переносятся в документ Отчет о розничных продажах.

Проанализируем, какой запрос используется при закрытии кассовой смены.

В общем модуле РозничныеПродажи есть функция ЗаполнитьОтчетОРозничныхПродажах. Именно в ней и содержится текст запроса, который получает данные о чеках ККМ, пробитых за текущую кассовую смену. Приведем фрагмент этой процедуры.

Функция ЗаполнитьОтчетОРозничныхПродажах(ОтчетОРозничныхПродажахОбъект, КассоваяСмена, ОписаниеОшибки = "") Экспорт
    
    УстановитьПривилегированныйРежим(Истина);
    
    // Заполнение отчета о розничных продажах
    Попытка
   	 
   	 МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
   	 
   	 // Подготовка данных.
   	 ТекстЗапроса =
         

Смотреть текст запроса

"ВЫБРАТЬ | ЧекККМТовары.Ссылка КАК Ссылка, | ЧекККМТовары.КлючСвязи КАК КлючСвязи, | ЧекККМТовары.Номенклатура КАК Номенклатура, | ЧекККМТовары.Характеристика КАК Характеристика, | ЧекККМТовары.Серия КАК Серия, | ЧекККМТовары.Упаковка КАК Упаковка, | ВЫРАЗИТЬ(ВЫБОР | КОГДА | ЧекККМТовары.СуммаРучнойСкидки + ЧекККМТовары.СуммаАвтоматическойСкидки = 0 | ИЛИ ЧекККМТовары.КоличествоУпаковок = 0 | ТОГДА | ЧекККМТовары.Цена | ИНАЧЕ | ЧекККМТовары.Сумма / ЧекККМТовары.КоличествоУпаковок | КОНЕЦ КАК Число(15,2)) КАК Цена, | ЧекККМТовары.СтавкаНДС КАК СтавкаНДС, | ЧекККМТовары.КоличествоУпаковок КАК КоличествоУпаковок, | ЧекККМТовары.Количество КАК Количество, | ЧекККМТовары.Сумма КАК Сумма, | ЧекККМТовары.СуммаНДС КАК СуммаНДС, | ЧекККМТовары.Ссылка.Склад КАК Склад, | ЧекККМТовары.Ссылка.Партнер КАК Партнер, | ЧекККМТовары.Помещение КАК Помещение, | ЧекККМТовары.Продавец КАК Продавец, | ЧекККМТовары.Ссылка.Валюта КАК Валюта, | ЧекККМТовары.Ссылка.ВидЦены КАК ВидЦены, | ЧекККМТовары.Ссылка.КассаККМ КАК КассаККМ, | ЧекККМТовары.Ссылка.Организация КАК Организация, | ЧекККМТовары.Ссылка.НалогообложениеНДС КАК НалогообложениеНДС | |ПОМЕСТИТЬ Товары | |ИЗ | Документ.ЧекККМ.Товары КАК ЧекККМТовары |ГДЕ | ЧекККМТовары.Ссылка.КассоваяСмена = &КассоваяСмена | И ЧекККМТовары.Ссылка.Проведен | И ЧекККМТовары.Ссылка.НомерЧекаККМ > 0 | |ОБЪЕДИНИТЬ ВСЕ | |ВЫБРАТЬ | ЧекККМТовары.Ссылка, | 0, | ЧекККМТовары.Номенклатура, | ЧекККМТовары.Характеристика, | ЧекККМТовары.Серия, | ЧекККМТовары.Упаковка, | ЧекККМТовары.Цена, | ЧекККМТовары.СтавкаНДС, | -ЧекККМТовары.КоличествоУпаковок, | -ЧекККМТовары.Количество, | -ЧекККМТовары.Сумма, | -ЧекККМТовары.СуммаНДС, | ЧекККМТовары.Ссылка.Склад, | ЧекККМТовары.Ссылка.Партнер, | ЧекККМТовары.Помещение, | ЧекККМТовары.Продавец, | ЧекККМТовары.Ссылка.Валюта, | ЧекККМТовары.Ссылка.ВидЦены, | ЧекККМТовары.Ссылка.КассаККМ, | ЧекККМТовары.Ссылка.Организация, | ЧекККМТовары.Ссылка.НалогообложениеНДС |ИЗ | Документ.ЧекККМВозврат.Товары КАК ЧекККМТовары |ГДЕ | ЧекККМТовары.Ссылка.КассоваяСмена = &КассоваяСмена | И ЧекККМТовары.Ссылка.Проведен | И ЧекККМТовары.Ссылка.НомерЧекаККМ > 0 |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ЧекККМТовары.Ссылка КАК Ссылка, | ЧекККМТовары.Номенклатура КАК Номенклатура, | ЧекККМТовары.Характеристика КАК Характеристика, | ЧекККМТовары.Серия КАК Серия, | ЧекККМТовары.Упаковка КАК Упаковка, | ЧекККМТовары.Цена КАК Цена, | ЧекККМТовары.СтавкаНДС КАК СтавкаНДС, | ЧекККМТовары.КоличествоУпаковок КАК КоличествоУпаковок, | ЧекККМТовары.Количество КАК Количество, | ЧекККМТовары.Сумма КАК Сумма, | ЧекККМТовары.СуммаНДС КАК СуммаНДС, | ЧекККМТовары.Склад КАК Склад, | ЧекККМТовары.Партнер КАК Партнер, | ЧекККМТовары.Помещение КАК Помещение, | ЧекККМТовары.Продавец КАК Продавец, | ЧекККМТовары.Валюта КАК Валюта, | ЧекККМТовары.ВидЦены КАК ВидЦены, | ЧекККМТовары.КассаККМ КАК КассаККМ, | ЧекККМТовары.Организация КАК Организация, | ЧекККМТовары.НалогообложениеНДС КАК НалогообложениеНДС | |ПОМЕСТИТЬ СписокТоваров |ИЗ | Товары КАК ЧекККМТовары |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ РАЗЛИЧНЫЕ | СписокТоваров.Ссылка КАК Ссылка |ПОМЕСТИТЬ ЧекиККМ |ИЗ | СписокТоваров КАК СписокТоваров |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ЧекиККМ.Ссылка КАК Ссылка |ИЗ | ЧекиККМ КАК ЧекиККМ |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ РАЗЛИЧНЫЕ | СписокТоваров.Валюта КАК Валюта, | СписокТоваров.ВидЦены КАК ВидЦены, | СписокТоваров.КассаККМ КАК КассаККМ, | СписокТоваров.Организация КАК Организация, | СписокТоваров.НалогообложениеНДС КАК НалогообложениеНДС, | СписокТоваров.Склад КАК Склад |ИЗ | СписокТоваров КАК СписокТоваров |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ РАЗЛИЧНЫЕ | СписокТоваров.Номенклатура КАК Номенклатура, | СписокТоваров.Характеристика КАК Характеристика, | СписокТоваров.Серия КАК Серия, | СписокТоваров.Упаковка КАК Упаковка, | СписокТоваров.Цена КАК Цена, | СписокТоваров.СтавкаНДС КАК СтавкаНДС |ИЗ | СписокТоваров КАК СписокТоваров |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | КассоваяСмена.ОкончаниеКассовойСмены КАК ОкончаниеКассовойСмены |Из | Документ.КассоваяСмена КАК КассоваяСмена |ГДЕ КассоваяСмена.Ссылка = &КассоваяСмена |";
Запрос = Новый Запрос; Запрос.Текст = ТекстЗапроса; Запрос.УстановитьПараметр("КассоваяСмена", КассоваяСмена); Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц; МассивРезультатов = Запрос.ВыполнитьПакет(); ... КонецФункции

В приведенном программном коде первым делом создается экземпляр менеджера временных таблиц. Именно в нем будут храниться создаваемые временные таблицы.

Далее создается запрос, осуществляется связь запроса с ранее созданным менеджером временных таблиц. Видно, что в тексте запроса несколько раз встречается ключевое слово ПОМЕСТИТЬ. Значит, при выполнении такого запроса происходит создание нескольких временных таблиц.

При отладке этого фрагмента программного кода может возникнуть потребность просмотреть содержимое временных таблиц. Рассмотрим, как это можно сделать.

В последней строке программного кода происходит выполнение пакета запросов. В результате система возвращает массив, куда последовательно помещаются результаты выполнения отдельных запросов пакета:

Рисунок 2

В пакете первый запрос создает временную таблицу Товары. Результат такого запроса содержит одну колонку Количество и одну строку, куда помещается количество записей в созданной временной таблице:

Рисунок 3

Выгрузим результат этого запроса в таблицу значений:

Рисунок 4

Можно увидеть, что в созданной временной таблице находятся три записи, но сами значения, помещенные во временную таблицу, отсутствуют, поскольку в результате запроса с ключевым словом ПОМЕСТИТЬ содержится только количество записей в созданной временной таблице, а не сами записи.

Чтобы просмотреть содержимое временной таблицы, в типовой конфигурации «Управление торговлей», редакция 11.3 была реализована вспомогательная экспортная функция ПоказатьВременнуюТаблицу общего модуля ОбщегоНазначенияУТ.

В качестве параметров нужно передать менеджер временных таблиц (или сам запрос) и имя самой временной таблицы, которую требуется просмотреть. Функция возвращает таблицу значений. Следовательно, в конфигураторе в окне Вычислить выражение можно получить саму временную таблицу:

Рисунок 5

Функция выглядит следующим образом:

Функция ПоказатьВременнуюТаблицу(МенеджерВременныхТаблицИлиЗапрос, ИмяВременнойТаблицы) Экспорт ЗакрытьМенеджерВременныхТаблиц = Ложь; Если ТипЗнч(МенеджерВременныхТаблицИлиЗапрос) = Тип("Запрос") Тогда Если МенеджерВременныхТаблицИлиЗапрос.МенеджерВременныхТаблиц = Неопределено Тогда МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц; ЗакрытьМенеджерВременныхТаблиц = Истина; МенеджерВременныхТаблицИлиЗапрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц; Иначе МенеджерВременныхТаблиц = МенеджерВременныхТаблицИлиЗапрос.МенеджерВременныхТаблиц; КонецЕсли; МенеджерВременныхТаблицИлиЗапрос.Выполнить(); Иначе МенеджерВременныхТаблиц = МенеджерВременныхТаблицИлиЗапрос; КонецЕсли; ДанныеТаблицы = ЗапросВыполнитьВыгрузить("ВЫБРАТЬ * ИЗ " + ИмяВременнойТаблицы,, МенеджерВременныхТаблиц); Если ЗакрытьМенеджерВременныхТаблиц Тогда МенеджерВременныхТаблиц.Закрыть(); МенеджерВременныхТаблицИлиЗапрос.МенеджерВременныхТаблиц = Неопределено; КонецЕсли; Возврат ДанныеТаблицы; КонецФункции Функция ЗапросВыполнитьВыгрузить(ТекстЗапроса, ПараметрыЗапроса = Неопределено, МенеджерВременныхТаблиц = Неопределено) Экспорт Запрос = Новый Запрос(ТекстЗапроса); Если МенеджерВременныхТаблиц <> Неопределено Тогда Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц; КонецЕсли; Если ЗначениеЗаполнено(ПараметрыЗапроса) Тогда Для Каждого Параметр Из ПараметрыЗапроса Цикл Запрос.УстановитьПараметр(Параметр.Ключ, Параметр.Значение); КонецЦикла; КонецЕсли; Возврат Запрос.Выполнить().Выгрузить(); КонецФункции

Итак, при помощи подобной функции можно при отладке просмотреть содержимое временной таблицы.

Функция ПоказатьВременнуюТаблицу из общего модуля ОбщегоНазначенияУТ присутствует в конфигурациях «Управление торговлей», редакция 11.3, «Комплексная автоматизация», редакция 2, «ERP Управление предприятием 2».

Если в конфигурации нет аналогичной функции (например, в «1С:Бухгалтерии» или «Управление небольшой фирмой» нет такого общего модуля и такой функции), то ее можно реализовать самостоятельно, например, в общем модуле, а затем использовать при отладке. Самый простой вариант функции будет выглядеть следующим образом:

Функция ПоказатьВременнуюТаблицу(МенеджерВременныхТаблиц, ИмяВременнойТаблицы) Экспорт Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц; Запрос.Текст = "ВЫБРАТЬ * ИЗ " + ИмяВременнойТаблицы; Возврат Запрос.Выполнить().Выгрузить(); КонецФункции

Свойства менеджера временных таблиц, появившиеся в платформе 8.3.8

В предыдущем разделе для получения содержимого временной таблицы нужно было воспользоваться функцией из конфигурации. Было бы намного удобнее, если бы возможности просмотра временных таблиц были реализованы прямо в платформе. И в платформе 8.3.8 такие возможности были добавлены.

У менеджера временных таблиц есть свойство Таблицы. Это коллекция, которая содержит временные таблицы, хранящиеся в менеджере временных таблиц:

Рисунок 6

Для каждой временной таблицы можно получить имя (свойство ПолноеИмя) и список колонок (свойство Колонки). Метод ПолучитьДанные() временной таблицы запроса возвращает значение типа РезультатЗапроса. Соответственно, можно вывести содержимое самой временной таблицы:

Рисунок 7

Также у объекта встроенного языка Запрос появился новый метод ВыполнитьПакетСПромежуточнымиДанными():

Рисунок 8

Результат работы этого метода аналогичен методу ВыполнитьПакет(), но есть важное отличие.

Когда используется метод ВыполнитьПакет(), то для временной таблицы в результате мы получаем количество записей, которое было помещено во временную таблицу. При использовании метода ВыполнитьПакетСПромежуточнымиДанными() вместо количества записей будет возвращено содержимое этой временной таблицы:

Рисунок 9

Значит, теперь нет необходимости реализовывать специальные функции в конфигурациях, а можно использовать новые возможности платформы.

Просмотр временных таблиц при проведении документа Расчет себестоимости в УПП 1.3

В конфигурации «Управление производственным предприятием», редакция 1.3 документ Расчет себестоимости – один из самых сложных с точки зрения используемых алгоритмов. И в запросах, которые выполняются при проведении этого документа, используется достаточно большое количество временных таблиц. И зачастую при отладке нужно знать, какие именно данные в этих таблицах размещаются.

Рассмотрим, какие возможности есть в конфигурации УПП.

Рассмотрим для примера, как просмотреть содержимое временной таблицы, которая формируется при проведении документа на шаге Расчет базы распределения косвенных расходов (используется партионный учет):

Рисунок 10

В конфигураторе устанавливаем точку останова в процедуре ОбработкаПроведения. В пользовательском режиме запускаем проведение документа. Происходит остановка на точке.

Теперь по шагам можно пройти все выполняемые строки программного кода, определить, где именно происходит расчет базы распределения. Это процедура ВыполнениеДействийДокумента в модуле объекта, где последовательно выполняются действия, указанные пользователем в форме документа. Для расчета базы происходит переход к процедуре РассчитатьБазуРаспределения общего модуля ПроцедурыРасчетаБазыРаспределенияЗатрат, в которой встречается следующий фрагмент программного кода:

// Вызывается процедура формирования запроса по временной таблице. Используется при отладке алгоритмов.
   	 // Для просмотра временной таблицы в структуре шапки документа поле "ОтладочныйРежим" должно иметь значение "Истина".
   	 ИмяВременнойТаблицы = "БазаРаспределения" + СуффиксИмениРегистра;
   	 РасширеннаяАналитикаУчета.ПоказатьВременнуюТаблицу(
   		 СтруктураПараметров,
   		 МенеджерВременныхТаблиц,
   		 ИмяВременнойТаблицы
   	 );

Сама процедура ПоказатьВременнуюТаблицу() выглядит следующим образом:

Процедура ПоказатьВременнуюТаблицу(
    СтруктураШапкиДокумента,
    МенеджерВременныхТаблиц,
    ИмяВременнойТаблицы
    ) Экспорт
    
    Если Не СтруктураШапкиДокумента.Свойство("ОтладочныйРежим")
     ИЛИ Не СтруктураШапкиДокумента.ОтладочныйРежим
    Тогда
   	 Возврат;
    КонецЕсли;
    
    ТекстЗапроса = "
    |ВЫБРАТЬ
    |    *
    |ИЗ
    |    ИмяВременнойТаблицы
    |";
    
    Запрос = Новый Запрос;
    Запрос.Текст = СтрЗаменить(ТекстЗапроса, "ИмяВременнойТаблицы", ИмяВременнойТаблицы);
    Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
    
    РезультатЗапроса = Запрос.Выполнить();
    
КонецПроцедуры // ПоказатьВременнуюТаблицу()

Первым делом необходимо включить отладочный режим в структуре шапки документа. Для этого в окне Вычислить выражение (Shift + F9) указать:

РасширеннаяАналитикаУчета.ВключитьОтладочныйРежим(СтруктураШапкиДокумента, Истина)

Рисунок 11

Подробнее описание этой функции можно найти в процедуре ПодготовитьСтруктуруШапкиДокумента() модуля объекта. В конце этой процедуры есть комментарий, описывающий включение отладочного режима.

Убедимся, что после вычисления этого выражения в структуре шапки документа свойство приняло нужное значение:

Рисунок 12

Анализируем программный код процедуры, становится понятно, что при включенном отладочном режиме можно получить содержимое временной таблицы. Это как раз и будет таблица, содержащая данные базы распределения:

Рисунок 13

Такие возможности для просмотра содержимого временных таблиц предоставляет конфигурация «Управление производственным предприятием».

Передача запроса из отладчика в консоль запросов

Один из самых удобных способов отладки запросов – это использование консоли запросов. В таком случае работать с запросом можно прямо в режиме «1С:Предприятие», сразу проверяя результат запроса на данных информационной базы. Также в большинстве консолей существует возможность просматривать содержимое временных таблиц запроса.

В таком случае отладка запросов может выглядеть следующим образом. Необходимо в конфигураторе получить готовый текст запроса, который требуется отладить. Для этого в простом случае достаточно будет только скопировать текст запроса из модуля в конфигураторе.

Часто в программном коде итоговый текст запроса собирается из отдельных «кусочков» при помощи конкатенации строк. В таком случае можно установить точку останова в коде и при помощи функции отладчика Вычислить выражение (Shift + F9) получить готовый текст запроса, который и будет выполняться. Этот текст запроса можно переносить в консоль запросов, запущенную в пользовательском режиме.

Затем в консоли необходимо установить параметры, которые используются при работе с запросом. И после этого запрос в консоли можно выполнять, просматривать результат запроса, корректировать текст запроса в случае возникновения ошибок, анализировать содержимое временных таблиц и т.д.

Итак, в статье мы рассмотрели основные приемы, которые можно использовать при отладке запросов с временными таблицами.

Применяйте эти приемы на практике, это существенно облегчит задачи по анализу и доработке типовых конфигураций! :)

Об авторе

Автор статьи – Василий Ханевич

PDF-версия статьи для участников группы ВКонтакте

Мы ведем группу ВКонтакте – http://vk.com/kursypo1c.

Если Вы еще не вступили в нее – сделайте это сейчас, и в блоке ниже (на этой странице) появятся ссылки на скачивание материалов.


Статья в PDF-форматеСтатья в PDF-формате
Вы можете скачать эту статью в формате PDF по следующей ссылке: Ссылка доступна для зарегистрированных пользователей)

Если Вы уже участник группы – нужно просто повторно авторизоваться в ВКонтакте, чтобы скрипт Вас узнал. В случае проблем решение стандартное: очистить кэш браузера или подписаться через другой браузер.

P.S.

Понимать, как работают запросы и уметь их строить - обязательный навык для всех, кто дорабатывает и внедряет 1С.

После курса Вы сможете:

  • Строить сложные запросы с несколькими источниками данных
  • Уверенно задействовать вложенные запросы и временные таблицы
  • Использовать встроенный язык для обработки результатов запроса
  • Учитывать особенности соединений и объединений нескольких таблиц.
  • Разрабатывать запросы на уровне задач Аттестации 1С:Специалист по платформе.
Программа, стоимость, условия и регистрация в группу: «Запросы в 1С 8.3, Базовый курс (с нуля до уровня Специалист по платформе)» Для всех, кто внедряет и дорабатывает 1С.

Комментарии / обсуждение (41):

  1. Ulvi Sultanoff (Baku)

    Функция ВыполнитьПакетСПромежуточнымиДанными(Запрос) Экспорт

    ПакетЗаросов = Запрос.ВыполнитьПакетСПромежуточнымиДанными();
    П = Новый Массив;
    Для Каждого РезультатЗапроса Из ПакетЗаросов Цикл
    Если ТипЗнч(РезультатЗапроса) = Тип(“РезультатЗапроса”) Тогда
    П.Добавить(Новый Структура(“РезультатЗапросаТЧ, РезультатЗапроса”, РезультатЗапроса.Выгрузить(), РезультатЗапроса));
    Иначе
    П.Добавить(Новый Структура(“РезультатЗапросаТЧ, РезультатЗапроса”, Неопределено, РезультатЗапроса));
    КонецЕсли;
    КонецЦикла;

    Возврат П;

    КонецФункции

    • Василий Ханевич

      Добрый день!
      Да, так можно использовать метод ВыполнитьПакетСПромежуточнымиДанными объекта типа Запрос.

  2. Алексей

    Здравствуйте.
    Спасибо за статью!
    А вы не знаете, как посмотреть не содержимое временных таблиц (благодаря этой статье увидел, как)
    А сам текст запроса временных таблиц?
    То есть, можно ли увидеть весь итоговый текст запроса. который исполняется?

    А то нашел модуль и функцию нужную в типовой конфе – результат правильный получается, но, хотел его воспроизвести в консоли, но, текста нет самих временных таблиц.

    Можно ли как-то увидеть текст целиком?

    • Василий Ханевич

      Добрый день!
      В таком случае нужно по шагам выполнять программный код, копировать отдельные фрагменты текста запроса и вставлять их в консоль запросов.
      Потому что в типовых конфигурациях часто встречается вот такой код:

      Запрос = Новый Запрос;
      Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
      Запрос.Текст =
      "ВЫБРАТЬ
      | ...
      |ПОМЕСТИТЬ ВременнаяТаблица1
      |ИЗ
      | ...";
      Запрос.Выполнить();
      ...
      Запрос.Текст =
      "ВЫБРАТЬ
      | ...
      |ПОМЕСТИТЬ ВременнаяТаблица2
      |ИЗ
      | ...";
      Запрос.Выполнить();

      Значение текста запроса заменяется. Поэтому получить итоговый текст запроса со всеми временными таблицами просто негде, нужно вручную собирать его по кусочкам для использования в консоли.

  3. Starhan

    А что делать, если в отладчике весь запрос не помещается в окно значения переменной?

    Собственно запрос там режется и в конце показывает многоточие (…).

    • Василий Ханевич

      Добрый день!
      Длинная строка может не помещаться в поле для просмотра значения, тогда отображается многоточие:
      Выражение
      При помощи кнопки с увеличительным стеклом можно открыть строку в отдельном окне, так поместится больше текста:
      Просмотр
      Однако и в этом отдельном окне может не поместиться весь текст большого запроса.
      Тогда можно применить прием, подсмотренный в одной из консоли запросов.

      Создаем внешнюю обработку ЗаписьСтрокиВФайл.epf. В модуле менеджера создаем экспортный метод:

      Функция ЗаписатьТекстВФайл(ТекстоваяСтрока, ИмяФайла) Экспорт

          Текст = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
          Текст.ЗаписатьСтроку(ТекстоваяСтрока);
          Текст.Закрыть();
         
      КонецФункции

      При отладке вычисляем вот такое выражение:

      ВнешниеОбработки.Создать("C:\Users\User1\Downloads\ЗаписьСтрокиВФайл.epf", Ложь).ЗаписатьТекстВФайл(Запрос.Текст, "C:\Users\User1\Downloads\Запрос.txt")

      Отладка
      При этом в текстовый файл, указанный в параметре, будет записан целиком текст запроса.

  4. Олег Бляхеров

    Добрый день!
    Если можно, добавлю свои пять копеек.
    Для отладки запросов можно использовать расширения. Годится это, правда, только для конфигураций, совместимых с 8.3.10 и старше, но, если очень нужно, можно сделать копию базы и в копии снять ограничения на совместимость.
    Итак, создаем новое расширение, расширяем в него интересующую нас процедуру с прагмой &после, в расширении процедуры имеем доступ к запросу и его менеджеру временных таблиц и можем делать любой анализ (хоть консоль запросов вызывай!).
    Например, можно выгрузить все временные таблицы в Excel:

    &После(“СоздатьДвижения”)
    Процедура Отладка_СоздатьДвижения(МенеджерВременныхТаблиц, Затраты, Протокол)

    ВывестиТаблицу(“Вершины”, Затраты.Вершины);
    ВывестиТаблицу(“Ребра”, Затраты.Ребра);
    ВывестиТаблицу(“Контуры”, Затраты.Контуры);
    ВывестиТаблицу(“ЦелевоеСальдо”, Затраты.ЦелевоеСальдо);
    Для каждого Таблица из МенеджерВременныхТаблиц.Таблицы Цикл
    ВывестиТаблицу(Таблица.ПолноеИмя, Таблица.ПолучитьДанные().Выгрузить());
    КонецЦикла;

    КонецПроцедуры

    Процедура ВывестиТаблицу(Имя, Таблица)

    ТабДок = новый ТабличныйДокумент;

    ТабДок.Область(1,1).Текст = Имя;
    Для Инд=0 по Таблица.Колонки.Количество()-1 Цикл
    ТабДок.Область(2,Инд+1).Текст = Таблица.Колонки[Инд].Имя;
    КонецЦикла;

    Для Инд1=0 по Таблица.Количество()-1 Цикл
    Для Инд2=0 по Таблица.Колонки.Количество()-1 Цикл
    ТабДок.Область(Инд1 + 3, Инд2 + 1).Текст = Строка(Таблица[Инд1][Инд2])
    КонецЦикла
    КонецЦикла;

    ТабДок.Записать(“e:\XXX\Отладка\” + Имя + “.xlsx”, ТипФайлаТабличногоДокумента.XLSX)

    КонецПроцедуры

    С уважением.

    • Олег Бляхеров

      С консолью запросов я, пожалуй, погорячился – процедуры с такими запросами исполняются на сервере, сорри…

      • Василий Ханевич

        Добрый день!
        Да, вполне можно использовать такой подход.
        Вопрос только в удобстве отладки таблиц в Excel.

  5. Рустем

    Спасибо за статью!
    Приемы и новшества актуальны, только ведь все понимают, что сопровождать, изменять, дорабатывать такие сложные запросы никому не хочется – я не прихожу в восторг от очередного задания разобраться в запросе – одно уныние от таких запросов: усложнять запросы можно до бесконечности. А выигрыш какой?!
    Основная проблема (и потеря времени) происходит тогда, когда надо быстро понять (прочесть) запрос, затем отладить его в консоли запросов с текущими параметрами – понять для чего он был создан, почему именно такие связи между полями таблиц, где тот ключевой показатель, который надо изменить?
    Я уверен, что временные виртуальные таблицы нужны, но не уверен, что нагромождать конфигурации большими кусочными запросами – это единственно правильный способ решить ту или иную задачу.
    Почему я убежден, что есть другой способ конфигурировать базы, потому что в свое время, разрабатывая конфигурацию, пошел по самому простому пути – для получения определенных данных стал формировать большие запросы. Получение данных с каждым годом замедлялось в разы – терпение лопнуло, когда я сформировал отчет за 8 часов.
    В результате я пошел от задачи и придумал механизм хранения промежуточных показателей в таблицах базы данных. Удобство заключалось еще и в том, что я мог в любой момент через пользовательский режим посмотреть регистры с отбором по нужным мне измерениям и провести визуальный анализ на предмет корректного расчета промежуточных сведений.
    Спустя год я описал это в статье, почему до сих пор это не стало повсеместным – думаю, потому что способ так решать задачи до сих пор не популярен: проще написать большой и сложный запрос.
    Вопрос к обсуждению: почему нельзя изменить сложные запросы УПП на схему хранения промежуточных сведений в самой базе данных?

    • Василий Ханевич

      Добрый день!
      Резонный вопрос. Но скорее всего, в УПП уже ничего не поменяется, развивать это решение не будут.
      А вот, например, в БП 3 я заметил движение в подобном направлении. В УПП понадобилось разобраться, почему декларация по налогу на имущество заполняется не так, как ожидается. Запросы там были достаточно сложные, выполнялись в цикле по периодам, состояли из отдельных временных таблиц и т.д. Потом смотрю, что в БП 3 есть отдельный регистр сведений РасчетНалогаНаИмущество, куда при закрытии месяца записываются уже подготовленные и структурированные данные. И декларация заполняется по этому регистру. Правда, сама процедура получения данных для записи в регистр достаточно сложная.
      Так что хранение промежуточных данных используется. Но для этого могут потребоваться методические изменения в прикладном решении.
      К тому же, чтобы подготовить эти промежуточные данные в общем случае может потребоваться также достаточно сложный алгоритм или объемный запрос, разделенный на отдельные кусочки.

  6. wealth

    Кроме инструментов разработчика пользуюсь глобальной процедурой парсинга запросов. Позволяет на лету посмотреть результат выполнения любого пакета, вложенного, запроса объединения. А также сохранить в файл sel со всеми параметрами. Очень удобно! Вот скриншот примера использования: https://yadi.sk/i/oqNcK0IJ3Mimcu

    Процедура парсинга и подробная инструкция внутри обработки ПарсерЗапроса_v2.16beta
    https://yadi.sk/d/PLG8TPru3Mimbp

    Уже и не помню, где ее скачал.

  7. Олег (другой ))

    Конечно замечательно что и в платформе и в конфигурациях появляются инструменты для удобства отладки..
    Но по сравнению с Инструментами Разработки 1С http://devtool1c.ucoz.ru/ они малофункциональны.

    Банальный пример: при отладке запроса вы сразу в консоли получаете не только текст но и все параметры! (коих в сложных случаях бывает не мало)

    И это не реклама! А желание поделиться!! потому что очень-и-очень продвинутый инстурмент. И очень часто я встречаю коллег которые ничегошеньки о нем не знают, хотя работают не первый год.

    Конечно, ввиду функциональности данный инструмент не всегда элементарен в использовании, но оно того стоит!

    • Антон

      Пробовали его запустить в ERPна управляемых, чтобы посмотреть/отредактировать план обмена не запустился вылетел. В других случаях не подводил, пригождался не раз при работе объектами конфигурации. Поиск битых ссылок.

      • tormozit

        Можете уточнить версию ИР, название инструмента, тип данных и описание ошибки?

  8. slava-hhh

    Спасибо, познавательная статья. Насчет существующей процедуры просмотра временных таблиц в УПП только сейчас узнал, я для этого в своем общем модуле подобную писал. Еще, для удобства, туда же прописал функцию сохранения параметров запроса на жесткий диск через таблицу значений и функцию ЗначениеВФайл (а то этих параметров может быть довольно много, руками в консоли запросов довольно запарно их заполнять), и сделал возможность загрузки этих параметров в консоль.

    • Василий Ханевич

      Пожалуйста!
      Да, вручную переносить значения параметров в консоль может быть долго, да и пропустить по невнимательности какое-нибудь значение можно, например, из массива.

  9. Николай

    Для отладки запросов в модуле ОбщегоНазначения есть экспортная функция ЗапросВСтрокуXML(Запрос) куда передается сам объект запроса при выполнении функции в окне Вычислить выражение получаем XML сериализованное XML представление которое в режиме предприятия вставляется в консользапросов и по команде Заполнить из XML консоль заполняет текст и что очень удобно значения параметров с которыми выполняется запрос. Но если у вас в параметрах используются списки значений или таблицы значений то появится ошибка, обработка не может обрабатывать такого рода параметры. Но это достаточно просто исправляется.

    • Василий Ханевич

      Добрый день!
      Такое поведение должна поддерживать используемая консоль запросов. А поскольку консолей запросов существует огромное множество, то не все смогут “понять” запрос в таком формате.
      Есть еще вариант. В консоли запросов реализована экспортная функция для отладки запросов. В отладчике останавливаемся на точке останова, в окне Вычислить выражение (Shift+F9) обращаемся к этой экспортной функции из внешней обработки (консоли запросов), в качестве параметра передаем объект встроенного языка типа Запрос. При попытке вычислить такое выражение в пользовательском режиме открывается консоль с текстом отлаживаемого запроса и со всеми установленными параметрами.

      • Николай

        Такое поведение тоже должна поддерживать консоль запросов. ) Помоему мы говорим об одной и той же консоли запросов которую можно скачать на сайте ИТС 1С.

        • Василий Ханевич

          Не только. Такая возможность есть в консоли запросов из состава Инструментов Разработчика и в некоторых других.

          • KoroteevSV

            Имеется ввиду в окне Вычислить выражение (Shift+F9) нужно написать что-то подобное: ВнешниеОбработки.Создать(“C:\Инструменты разработчика\6_4.23\Модули\ирКонсольЗапросов.epf”).ОткрытьДляОтладки(Запрос)

            точка останова установлена перед строкой кода: РезультатЗапроса = Запрос.ВыполнитьПакет()

            И должна открыться консоль пользовательском режиме??

            • Василий Ханевич

              Да, должна открыться консоль в пользовательском режиме. Можно использовать следующий код:

              ВнешниеОбработки.Создать("C:\...\ирПортативный.epf", Ложь).Отладить(Запрос)
      • KoroteevSV

        Я попытался сделать так, как вы описали

        ВнешниеОбработки.Создать(“C:\Инструменты разработчика\6_4.23\Модули\ирКонсольЗапросов.epf”).ОткрытьДляОтладки(Запрос)

        Но окно отладки выдает ошибку, мол не найдено такого метода

      • veiuper

        В консоли запросов реализована экспортная функция для отладки запросов.
        Подскажите пожалуйста наименование этой экспортной процедуры. Не получается найти.

        • Василий Ханевич

          Добрый день!
          В консоли ИР можно использовать следующий код:

          ВнешниеОбработки.Создать("C:\...\ирПортативный.epf", Ложь).Отладить(Запрос)
            • Василий Ханевич

              Да, это было про ИР.
              Для консоли с сайта ИТС нужно обратиться к общему модулю ОбщегоНазначения, функция ЗапросВСтрокуXML:
              БСП
              Это общий модуль из БСП, поэтому не придется дорабатывать свои конфигурации.
              В комментарии перед функцией расписано, как ей пользоваться для отладки.
              Также можно обратиться к справочной информации из консоли запросов, там также рассказывается порядок действий для отладки.

    • veiuper

      Но это достаточно просто исправляется.
      Подскажите пожалуйста как это исправляется.

      • Василий Ханевич

        Предполагаю, что имелась в виду функция ПрочитатьЗапросыИзФайлаXML, расположенная в модуле объекта консоли запросов с сайта ИТС (файл ИнструментыРазработчикаКонсольЗапросов.epf). В этом коде явно обрабатываются типы СписокЗначений, ТаблицаЗначений и т.д.

        • veiuper

          Дополнительно опишу ту последовательность действий, которую не смог повторить или неверно делаю.
          1. “Забираю” в отладке текст запроса из конфигуратора в XML формате, используя ОбщегоНазначения.ЗапросВСтрокуXML(Запрос).
          2. Вставляю запрос в консоль для управляемого приложения и нажимаю “Прочитать из XML”.
          3. Получаю ошибку, т.к. у запроса есть параметр в виде таблицы значений.

          На этом этапе я и задал вопрос как это исправляется.
          Предварительно смотрел формат файла q1c и текста сформированного ОбщегоНазначения.ЗапросВСтрокуXML – отличаются. Даже пробовал вставить этот текст в файл qlc и пробовал открыть в консолях. Ни в какую.

          • Василий Ханевич

            Добрый день!
            Повторяю Ваши действия – возникает ошибка из-за типа параметра (таблицы значений). Нахожу строку кода, где эта ошибка возникает – это функция ИмяТипаИзЗначения в модуле объекта обработки. В этой функции таблица значений не анализируется, добавляю этот тип в код:

            ...
                ИначеЕсли ТипЗнч(Значение) = Тип("ТаблицаЗначений") Тогда
                    ИмяТипа = "ТаблицаЗначений";
            ...

            После этого ошибка не возникает.

            • veiuper

              Спасибо большое. Кучу времени теперь можно экономить, не занимаясь переносом таблиц значений в параметры консоли запросов.

  10. mr.Masuyk

    Спасибо за статью, полезно!
    Непонятно:
    “Часто в программном коде итоговый текст запроса собирается из отдельных «кусочков» при помощи конкатенации строк. В таком случае можно установить точку останова в коде и при помощи функции отладчика Вычислить выражение (Shift + F9) получить готовый текст запроса”.

    Вот код:
    Процедура ЗапросКусочками(Запрос)
    Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
    Запрос.Текст = “”;
    Запрос.Выполнить;

    Запрос.Текст = “”;
    Запрос.Выполнить;
    ..

    Запрос.Текст = “”; Запрос.Выполнить;

    Запрос.Текст = “Выбрать * Из “;
    //Результат ..
    КонецПроцедуры;

    Поставив точку остановы в конец процедуры я получу часть текста запроса, а именно концовку (Выбрать * Из ). Текстов из временных таблиц у меня не будет. В КонсольЗапросов такой текст не отработает.
    И то я привел простой пример, где процедура одна. В типовом коде чаще всего Запрос бегает из одной процедуры в другую, текста временных таблиц лежат в разных местах. Приходится анализировать программный код, вытаскивать все с помощью отладчика по шагам проходить километры кода и восстанавливать весь текст запроса.
    Как поступать в этой ситуации? Как получить целый текст запроса?

    • Василий Ханевич

      Добрый день!
      Да, именно так. Из-за того, что составление текста запроса в коде может быть разделено на несколько процедур, общих модулей и т.д., нет какого-то универсального способа. При помощи отладчика нужно проходить весь программный код, собирая текст запроса в единое целое. Да, это может быть долго, неудобно, также требуется внимательность, чтобы не пропустить какие-нибудь отдельные временные таблицы, без которых запрос целиком не отработает.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Вход на сайт

Зарегистрироваться

Подтверждение регистрации будет отправлено на указанный e-mail.

Я подтверждаю, что ознакомлен(а) с Пользовательским соглашением, принимаю его условия и даю свое согласие на обработку моих персональных данных.

Восстановить доступ

E-mail или логин

Ссылка на создание нового пароля будет отправлена на указанный e-mail.